<template>
  <div class="streaming-chat">
    <div class="chat-header">
      <h2>流式聊天接口测试</h2>
      <p class="api-info">接口地址: http://47.109.177.78:6300/aiapi/v1/dify/chat-messages/stream (直连模式)</p>
      <div class="proxy-info">
        <span class="direct-badge">⚡ 直连模式</span>
        <span>直接访问 API 无需代理</span>
        <span class="auth-badge">🔐 已配置认证</span>
      </div>
    </div>

    <div class="chat-container">
      <!-- 聊天消息显示区域 -->
      <div class="messages-container" ref="messagesContainer">
        <div 
          v-for="(message, index) in messages" 
          :key="index" 
          :class="['message', message.type]"
        >
          <div class="message-content">
            <div class="message-text" v-html="formatMessage(message.content)"></div>
            <div class="message-time">{{ message.timestamp }}</div>
          </div>
        </div>
        
        <!-- 正在输入指示器 -->
        <div v-if="isStreaming" class="typing-indicator">
          <div class="typing-dots">
            <span></span>
            <span></span>
            <span></span>
          </div>
          <span>AI正在回复...</span>
        </div>
      </div>

      <!-- 输入区域 -->
      <div class="input-container">
        <div class="input-group">
          <textarea
            v-model="currentQuery"
            @keydown="handleKeyDown"
            placeholder="请输入您的问题..."
            class="query-input"
            rows="3"
            :disabled="isStreaming"
          ></textarea>
          <button 
            @click="sendMessage" 
            :disabled="!currentQuery.trim() || isStreaming"
            class="send-button"
          >
            {{ isStreaming ? '发送中...' : '发送' }}
          </button>
        </div>
      </div>
    </div>

    <!-- 状态和错误信息 -->
    <div class="status-panel">
      <div v-if="connectionStatus" class="status-info">
        <span :class="['status-indicator', connectionStatus.type]"></span>
        {{ connectionStatus.message }}
      </div>
      
      <div v-if="error" class="error-message">
        <strong>错误:</strong> {{ error }}
      </div>
    </div>

    <!-- 调试信息 -->
    <div class="debug-panel" v-if="showDebug">
      <h3>调试信息</h3>
      <div class="debug-content">
        <div><strong>用户ID:</strong> {{ userId }}</div>
        <div><strong>连接状态:</strong> {{ isStreaming ? '连接中' : '已断开' }}</div>
        <div><strong>最后响应时间:</strong> {{ lastResponseTime || '无' }}</div>
        <div><strong>API模式:</strong> {{ useProxy ? '代理模式' : '直连模式' }}</div>
        <div><strong>当前API地址:</strong> {{ getCurrentApiUrl() }}</div>
      </div>
    </div>

    <!-- 控制按钮 -->
    <div class="controls">
      <button @click="clearMessages" class="clear-button">清空对话</button>
      <button @click="showDebug = !showDebug" class="debug-toggle">
        {{ showDebug ? '隐藏调试' : '显示调试' }}
      </button>
      <button @click="toggleProxyMode" class="proxy-toggle" :disabled="isStreaming">
        {{ useProxy ? '切换到直连模式' : '切换到代理模式' }}
      </button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, nextTick, onMounted } from 'vue'

interface Message {
  type: 'user' | 'assistant'
  content: string
  timestamp: string
}

interface ConnectionStatus {
  type: 'success' | 'error' | 'warning' | 'info'
  message: string
}

// 响应式数据
const messages = ref<Message[]>([])
const currentQuery = ref('')
const isStreaming = ref(false)
const error = ref('')
const connectionStatus = ref<ConnectionStatus | null>(null)
const showDebug = ref(false)
const lastResponseTime = ref('')
const messagesContainer = ref<HTMLElement>()
const useProxy = ref(false) // 默认使用直连模式

// 生成用户ID
const userId = ref(`user_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`)

// API配置 - 使用代理路径避免跨域问题
const API_URL_PROXY = '/aiapi/v1/dify/chat-messages/stream'
const API_URL_DIRECT = 'http://47.109.177.78:6300/aiapi/v1/dify/chat-messages/stream'

// 请求头配置
const AUTH_TOKEN = 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE3NTY4MDc1MzMsImlzcyI6InRpZ3Nob3AiLCJzdWIiOiIxMzI1ODM2NTQyMSIsImV4cCI6MTc1OTM5OTUzMywidXNlcm5hbWUiOiIxMzI1ODM2NTQyMSIsImlzQWRtaW4iOmZhbHNlLCJ1c2VySWQiOjd9.ZdjwTTd7h7jfAgJvDwe7lGoqtU1MEEziBDA6TpZFdE_t2RV6JyU9wKPkHmcCtSbAnx7DMU0QlhNkxeG7C4Y33w'

// 获取当前使用的API地址
const getCurrentApiUrl = () => {
  return useProxy.value ? API_URL_PROXY : API_URL_DIRECT
}

// 初始化
onMounted(() => {
  addSystemMessage('欢迎使用流式聊天接口测试！已更新为新的API地址和认证配置。默认使用直连模式。请输入您的问题。')
})

// 添加系统消息
const addSystemMessage = (content: string) => {
  messages.value.push({
    type: 'assistant',
    content,
    timestamp: new Date().toLocaleTimeString()
  })
}

// 添加用户消息
const addUserMessage = (content: string) => {
  messages.value.push({
    type: 'user',
    content,
    timestamp: new Date().toLocaleTimeString()
  })
}

// 添加助手消息
const addAssistantMessage = (content: string) => {
  messages.value.push({
    type: 'assistant',
    content,
    timestamp: new Date().toLocaleTimeString()
  })
}

// 更新最后一条助手消息
const updateLastAssistantMessage = (content: string) => {
  const lastMessage = messages.value[messages.value.length - 1]
  if (lastMessage && lastMessage.type === 'assistant') {
    lastMessage.content = content
    lastMessage.timestamp = new Date().toLocaleTimeString()
  } else {
    addAssistantMessage(content)
  }
}

// 格式化消息内容
const formatMessage = (content: string) => {
  return content.replace(/\n/g, '<br>')
}

// 滚动到底部
const scrollToBottom = () => {
  nextTick(() => {
    if (messagesContainer.value) {
      messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight
    }
  })
}

// 发送消息
const sendMessage = async () => {
  if (!currentQuery.value.trim() || isStreaming.value) {
    return
  }

  const query = currentQuery.value.trim()
  currentQuery.value = ''
  error.value = ''
  
  // 添加用户消息
  addUserMessage(query)
  scrollToBottom()

  // 设置流式状态
  isStreaming.value = true
  connectionStatus.value = {
    type: 'info',
    message: '正在连接到服务器...'
  }

  try {
    // 准备请求数据
    const requestData = {
      query: query,
      response_mode: "streaming",
      user: userId.value
    }

    console.log('发送请求:', requestData)

    // 发起流式请求
    const headers: Record<string, string> = {
      'Content-Type': 'application/json',
      'Authorization': AUTH_TOKEN  // 始终添加 Authorization 头
    }
    
    const response = await fetch(getCurrentApiUrl(), {
      method: 'POST',
      headers,
      body: JSON.stringify(requestData)
    })

    if (!response.ok) {
      throw new Error(`HTTP错误: ${response.status} ${response.statusText}`)
    }

    if (!response.body) {
      throw new Error('响应体为空')
    }

    connectionStatus.value = {
      type: 'success',
      message: '已连接，正在接收数据...'
    }

    // 处理流式响应
    const reader = response.body.getReader()
    const decoder = new TextDecoder()
    let accumulatedContent = ''

    while (true) {
      const { done, value } = await reader.read()
      
      if (done) {
        break
      }

      const chunk = decoder.decode(value, { stream: true })
      console.log('接收到数据块:', chunk)

      // 处理数据块
      const lines = chunk.split('\n')
      
      for (const line of lines) {
        if (line.trim() === '') continue
        
        // 检查是否是数据行
        if (line.startsWith('data: ')) {
          const data = line.slice(6).trim()
          
          // 跳过结束标记
          if (data === '[DONE]') {
            continue
          }

          try {
            const jsonData = JSON.parse(data)
            console.log('解析的JSON数据:', jsonData)
            
            // 根据不同的事件类型处理数据
            if (jsonData.event === 'message') {
              if (jsonData.answer) {
                accumulatedContent += jsonData.answer
                updateLastAssistantMessage(accumulatedContent)
                scrollToBottom()
              }
            } else if (jsonData.event === 'message_end') {
              // 消息结束
              console.log('消息传输完成')
            } else if (jsonData.answer) {
              // 直接包含答案内容
              accumulatedContent += jsonData.answer
              updateLastAssistantMessage(accumulatedContent)
              scrollToBottom()
            }
          } catch (parseError) {
            console.warn('解析JSON失败:', parseError, '原始数据:', data)
            // 如果不是JSON格式，可能是纯文本
            if (data && data !== '[DONE]') {
              accumulatedContent += data
              updateLastAssistantMessage(accumulatedContent)
              scrollToBottom()
            }
          }
        }
      }
      
      lastResponseTime.value = new Date().toLocaleTimeString()
    }

    // 如果没有收到任何内容，添加默认消息
    if (!accumulatedContent) {
      addAssistantMessage('抱歉，没有收到有效的响应内容。')
    }

    connectionStatus.value = {
      type: 'success',
      message: '消息接收完成'
    }

  } catch (err) {
    console.error('请求失败:', err)
    let errorMessage = ''
    
    if (err instanceof TypeError && err.message.includes('fetch')) {
      if (useProxy.value) {
        errorMessage = '代理请求失败，请检查服务器是否可访问'
      } else {
        errorMessage = '直连请求失败，请检查网络和服务器状态'
      }
    } else {
      errorMessage = err instanceof Error ? err.message : '未知错误'
    }
    
    error.value = errorMessage
    addAssistantMessage(`抱歉，发生了错误: ${errorMessage}`)
    
    connectionStatus.value = {
      type: 'error',
      message: `连接失败: ${errorMessage}`
    }
    
    // 如果是直连模式遇到错误，提示检查网络和服务器状态
    if (!useProxy.value && err instanceof TypeError) {
      addAssistantMessage('请检查网络连接和服务器状态，或者尝试切换到代理模式。')
    }
  } finally {
    isStreaming.value = false
    scrollToBottom()
  }
}

// 处理键盘事件
const handleKeyDown = (event: KeyboardEvent) => {
  if (event.key === 'Enter' && !event.shiftKey) {
    event.preventDefault()
    sendMessage()
  }
}

// 清空对话
const clearMessages = () => {
  messages.value = []
  error.value = ''
  connectionStatus.value = null
  addSystemMessage('对话已清空，请输入新的问题。')
}

// 切换代理模式
const toggleProxyMode = () => {
  useProxy.value = !useProxy.value
  const mode = useProxy.value ? '代理模式' : '直连模式'
  addSystemMessage(`已切换到${mode}，当前 API 地址: ${getCurrentApiUrl()}`)
  
  if (!useProxy.value) {
    connectionStatus.value = null  // 直连模式不显示跨域警告
  } else {
    connectionStatus.value = null
  }
}
</script>

<style scoped>
.streaming-chat {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

.chat-header {
  text-align: center;
  margin-bottom: 20px;
  padding: 20px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  border-radius: 12px;
}

.chat-header h2 {
  margin: 0 0 10px 0;
  font-size: 1.8rem;
}

.api-info {
  margin: 0 0 10px 0;
  font-size: 0.9rem;
  opacity: 0.9;
  word-break: break-all;
}

.proxy-info {
  display: flex;
  align-items: center;
  gap: 10px;
  justify-content: center;
  margin-top: 10px;
  font-size: 0.85rem;
}

.proxy-badge {
  background: rgba(255, 255, 255, 0.2);
  padding: 4px 8px;
  border-radius: 12px;
  font-size: 0.8rem;
}

.direct-badge {
  background: rgba(76, 175, 80, 0.3);
  color: white;
  padding: 4px 8px;
  border-radius: 12px;
  font-size: 0.8rem;
}

.auth-badge {
  background: rgba(76, 175, 80, 0.8);
  color: white;
  padding: 4px 8px;
  border-radius: 12px;
  font-size: 0.8rem;
}

.chat-container {
  background: white;
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  margin-bottom: 20px;
}

.messages-container {
  height: 500px;
  overflow-y: auto;
  padding: 20px;
  background: #f8f9fa;
}

.message {
  margin-bottom: 15px;
  display: flex;
  animation: fadeIn 0.3s ease-in;
}

.message.user {
  justify-content: flex-end;
}

.message.assistant {
  justify-content: flex-start;
}

.message-content {
  max-width: 70%;
  padding: 12px 16px;
  border-radius: 18px;
  position: relative;
}

.message.user .message-content {
  background: #007bff;
  color: white;
  border-bottom-right-radius: 4px;
}

.message.assistant .message-content {
  background: white;
  color: #333;
  border: 1px solid #e0e0e0;
  border-bottom-left-radius: 4px;
}

.message-text {
  line-height: 1.4;
  word-wrap: break-word;
}

.message-time {
  font-size: 0.75rem;
  opacity: 0.7;
  margin-top: 5px;
  text-align: right;
}

.message.assistant .message-time {
  text-align: left;
}

.typing-indicator {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  background: white;
  border-radius: 18px;
  border: 1px solid #e0e0e0;
  max-width: 200px;
  margin-bottom: 15px;
}

.typing-dots {
  display: flex;
  gap: 4px;
}

.typing-dots span {
  width: 6px;
  height: 6px;
  background: #999;
  border-radius: 50%;
  animation: typing 1.4s infinite;
}

.typing-dots span:nth-child(2) {
  animation-delay: 0.2s;
}

.typing-dots span:nth-child(3) {
  animation-delay: 0.4s;
}

.input-container {
  padding: 20px;
  background: white;
  border-top: 1px solid #e0e0e0;
}

.input-group {
  display: flex;
  gap: 10px;
  align-items: flex-end;
}

.query-input {
  flex: 1;
  border: 2px solid #e0e0e0;
  border-radius: 12px;
  padding: 12px 16px;
  font-size: 14px;
  resize: vertical;
  min-height: 50px;
  transition: border-color 0.3s;
}

.query-input:focus {
  outline: none;
  border-color: #007bff;
}

.query-input:disabled {
  background: #f5f5f5;
  cursor: not-allowed;
}

.send-button {
  background: #007bff;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 12px 24px;
  font-size: 14px;
  cursor: pointer;
  transition: background-color 0.3s;
  white-space: nowrap;
}

.send-button:hover:not(:disabled) {
  background: #0056b3;
}

.send-button:disabled {
  background: #6c757d;
  cursor: not-allowed;
}

.status-panel {
  margin-bottom: 20px;
}

.status-info {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 15px;
  border-radius: 8px;
  background: #f8f9fa;
  border: 1px solid #dee2e6;
}

.status-indicator {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

.status-indicator.success {
  background: #28a745;
}

.status-indicator.error {
  background: #dc3545;
}

.status-indicator.warning {
  background: #ffc107;
}

.status-indicator.info {
  background: #17a2b8;
}

.error-message {
  background: #f8d7da;
  color: #721c24;
  padding: 12px 15px;
  border-radius: 8px;
  border: 1px solid #f5c6cb;
  margin-top: 10px;
}

.debug-panel {
  background: #f8f9fa;
  border: 1px solid #dee2e6;
  border-radius: 8px;
  padding: 15px;
  margin-bottom: 20px;
}

.debug-panel h3 {
  margin: 0 0 10px 0;
  font-size: 1.1rem;
  color: #495057;
}

.debug-content div {
  margin-bottom: 5px;
  font-size: 0.9rem;
}

.controls {
  display: flex;
  gap: 10px;
  justify-content: center;
}

.clear-button, .debug-toggle, .proxy-toggle {
  background: #6c757d;
  color: white;
  border: none;
  border-radius: 8px;
  padding: 10px 20px;
  cursor: pointer;
  transition: background-color 0.3s;
}

.clear-button:hover {
  background: #5a6268;
}

.debug-toggle:hover {
  background: #5a6268;
}

.proxy-toggle {
  background: #17a2b8;
}

.proxy-toggle:hover:not(:disabled) {
  background: #138496;
}

.proxy-toggle:disabled {
  background: #6c757d;
  cursor: not-allowed;
  opacity: 0.6;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes typing {
  0%, 60%, 100% {
    transform: translateY(0);
  }
  30% {
    transform: translateY(-10px);
  }
}

/* 响应式设计 */
@media (max-width: 768px) {
  .streaming-chat {
    padding: 10px;
  }
  
  .messages-container {
    height: 400px;
  }
  
  .message-content {
    max-width: 85%;
  }
  
  .input-group {
    flex-direction: column;
    align-items: stretch;
  }
  
  .controls {
    flex-direction: column;
  }
}
</style>